// http.ts
import axios from 'axios';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';

// 用于存储请求的标识，便于路由切换时取消请求
const cancelTokenStore: any = {
  source: {
    token: null,
    cancel: null
  }
};

/** 接口响应通过格式 */
export interface HttpResponse {
  status: number;
  statusText: string;
  data: {
    code: number;
    desc: string;
    [key: string]: any;
  };
}

// 请求状态码
const showStatus = (status: number) => {
  let message = '';
  switch (status) {
    case 400:
      message = '请求错误(400)';
      break;
    case 401:
      message = '未授权，请重新登录(401)';
      break;
    case 403:
      message = '拒绝访问(403)';
      break;
    case 404:
      message = '请求出错(404)';
      break;
    case 408:
      message = '请求超时(408)';
      break;
    case 500:
      message = '服务器错误(500)';
      break;
    case 501:
      message = '服务未实现(501)';
      break;
    case 502:
      message = '网络错误(502)';
      break;
    case 503:
      message = '服务不可用(503)';
      break;
    case 504:
      message = '网络超时(504)';
      break;
    case 505:
      message = 'HTTP版本不受支持(505)';
      break;
    default:
      message = `连接出错(${status})!`;
  }
  return `${message}，请检查网络或联系管理员！`;
};

/**
 * 清空所有请求（通常在路由跳转时调用）
 */
export const clearAllPending = () => {
  const CancelToken = axios.CancelToken;
  cancelTokenStore.source.cancel && cancelTokenStore.source.cancel();
  cancelTokenStore.source = CancelToken.source();
};

const service = axios.create({
  // 联调
  baseURL: '/api',
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  },

  // 是否跨站点访问控制请求
  withCredentials: true,
  timeout: 3000, //超时时间，单位毫秒
  timeoutErrorMessage: '超时，请稍后再尝试',
  validateStatus() {
    // 使用async-await，处理reject情况较为繁琐，所以全部返回resolve，在业务代码中处理异常
    return true;
  },
  transformRequest: [
    data => {
      data = JSON.stringify(data);
      return data;
    }
  ],
  transformResponse: [
    data => {
      if (typeof data === 'string' && data.startsWith('{')) {
        data = JSON.parse(data);
      }
      return data;
    }
  ]
});

// 请求拦截器
service.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    config.cancelToken = cancelTokenStore.source.token;
    console.log(cancelTokenStore.source);

    //获取token，并将其添加至请求头中
    // const token = localStorage.getItem('token');
    // if (token) config.headers.Authorization = `${token}`;

    return config;
  },
  error => {
    // 错误抛到业务代码
    error.data = {};
    error.data.msg = '请求异常，请联系管理员！';
    return Promise.resolve(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    const status = response.status;
    let msg = '';
    if (status < 200 || status >= 300) {
      // 处理http错误，抛到业务代码
      msg = showStatus(status);
      if (typeof response.data === 'string') {
        response.data = { msg };
      } else {
        response.data.msg = msg;
      }
    }
    console.log('请求结果 ', response);
    return response;
  },
  error => {
    if (axios.isCancel(error)) {
      console.log('请求出错1: ', error);
    } else {
      // 错误抛到业务代码
      console.log('请求出错2: ', error);
      const originalRequest = error.config;
      if (error.code == 'ECONNABORTED' && error.message.indexOf('timeout') != -1) {
        originalRequest._retry = originalRequest._retry || 0;
        if (originalRequest._retry >= 5) {
          return Promise.reject(error);
        }
        originalRequest._retry += 1;
        return axios.request(originalRequest);
      }
    }

    return Promise.reject(error);
  }
);

export default service;
